#pragma once

#include "Misc/EngineEditorMacros.h"
#include "Containers/String.h"
#include "Reflection/Reflection.h"
#include "Containers/SharedObjectPtr.h"
#include "Math/Color.h"
#include "EditorScriptToken.m.h"

class REditorScriptFile;

RSTRUCT(ExtraHeader= "Language/EditorScriptFile.h")
struct SDocumentRange
{
    ROBJECT

public:
    //first char index
    //base 0
    RFIELD()
    int64_t StartCharIndex=-1;
    RFIELD()
    int64_t EndCharIndex=-1;

    RFIELD()
    TSharedObjectPtr<REditorScriptFile> File;

};


struct SEditorScriptErrorMessage
{
    SDocumentRange Range;
    CString Content;
};

enum class EEditorScriptTokenType
{
    Unknow,
    Comment,
    NormalKeyword, // class struct enum .etc
    FlowControlKeyword, //if, else, for, while return break continue.
    Operator, // + - * / % = == != > < >= <=

    InnerType, // void int, float, bool, string .etc

    LiteralString, // "xxx"
    LiteralNumber, // 123 221.f 0x123
    LiteralBool, // true false

    Identifier, //variable/function/class .etc name 

    LeftBrace, // {
    RightBrace, // }
    LeftParentheses, // (
    RightParentheses, // )
    LeftBracket, // [
    RightBracket, // ]

    Using, //using
    Namespace, //namespace
    Class, //class
    Struct, //struct
    Enum, //enum

    Dot, //.
    SemiColon, //;
    Colon, //:
    Comma, //,
};


// enum class EEditorIdentifierType
// {
//     Variable,
//     Function,
//     Class,
//     Namespace,
//     Struct,
//     Enum,
//     EnumValue,
// };

RSTRUCT()
struct SEditorScriptToken
{
    ROBJECT

public:
    //token range is [StartCharIndex, EndCharIndex]
    SDocumentRange Range;

    EEditorScriptTokenType TokenType=EEditorScriptTokenType::Unknow;

    SColor Color;

    // //only valid when TokenType is Identifier
    // //value of the identifier
    // CString IdentifierName; 

    // //only valid when TokenType is Identifier
    // //parent scope name of the identifier
    // //if the identifier is function name, the IdentifierParentName is the class name
    // //if the identifier is class name, the IdentifierParentName is the namespace name
    // //if the identifier is namespace name, the IdentifierParentName might be empty
    // //
    // CString IdentifierParentName;

    // //only valid when TokenType is Identifier
    // //the type of the identifier
    // EEditorIdentifierType IdentifierType;

};